package server.users;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import json.JSONObjectWrapper;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

import server.database.DatabaseColumn;
import server.database.DatabaseService;
import server.database.query.IQueryResult;
import server.servlet.AbstractServlet;
import utils.StringUtils;

import com.google.common.collect.Lists;

public class UsersServlet extends AbstractServlet
{
	private static final long serialVersionUID = 839765520084151296L;

	public static final String PATH = API + "/login";

	public static final String INCORRECT_USERNAME_PASSOWRD = "Incorrect username/password";
	public static final String USER_ALREADY_EXISTS = "Username already exists";

	public static final String USER = "user";
	public static final String USERS = "users";

	public static final String REGISTER = "register";
	public static final String AUTHORIZE = "authorize";

	public static final String NOT_AUTHORIZED = "-1";
	public static final String ADMIN = "0";
	public static final String MANAGER = "1";
	public static final String SALESMAN = "2";

	@Override
	protected void doGetSpecific(HttpServletRequest request, HttpServletResponse response, JSONObject output) throws ServletException, IOException
	{
		String sUsername = request.getParameter(getTable().USERNAME.getName());
		if (null != sUsername)
		{
			login(request, response, output);
		}
		else
		{
			getAllUsers(request, response, output);
		}

	}

	private void getAllUsers(HttpServletRequest request, HttpServletResponse response, JSONObject output)
	{
		UsersTable users = getTable();

		List<DatabaseColumn> lstFields = Lists.newArrayList();
		List<String> lstValues = Lists.newArrayList();

		lstFields.add(UsersTable.ROLE);
		lstValues.add(ADMIN);
		lstFields.add(UsersTable.ROLE);
		lstValues.add(MANAGER);
		lstFields.add(UsersTable.ROLE);
		lstValues.add(SALESMAN);

		IQueryResult queryResult = users.getAllEntities(lstFields, lstValues, UsersTable.OR);

		if (queryResult.getResult() == IQueryResult.SUCESS)
		{
			output.put(RESULT, true);

			JSONArray entities = new JSONArray();
			buildEntityValues(queryResult.getResultValues(), entities, getTable());

			output.put(USERS, entities);

		}
		else if (queryResult.getResult() != IQueryResult.NO_RESULTS)
		{
			setFail(output, UNEXPECTED_ERROR, UNEXPECTED_ERROR);
		}

	}

	private void login(HttpServletRequest request, HttpServletResponse response, JSONObject output)
	{
		String sUsername = request.getParameter(getTable().USERNAME.getName());
		String sPassword = request.getParameter(getTable().PASSWORD.getName());
		// TODO - password needs to be encrypted before going to DB
		UsersTable users = getTable();

		IQueryResult queryResult = users.login(sUsername, sPassword);
		output.put(QUERY_RESULT, queryResult.getResult());

		if (queryResult.getResult() == IQueryResult.SUCESS)
		{
			output.put(RESULT, true);

			Map<String, String> resultMap = queryResult.getResultValues().get(0);

			JSONObject user = buildEntityValue(resultMap, users);
			output.put(USER, user);
		}
		else
		{
			setFail(output, INCORRECT_USERNAME_PASSOWRD, INCORRECT_USERNAME_PASSOWRD);
		}
	}

	@Override
	protected void doPostSpecific(JSONObjectWrapper request, JSONObject output) throws ServletException, IOException
	{
		JSONObjectWrapper entity = request.getJsonValue(USER);

		String sID = entity.getStringValue(UsersTable.ID.getName());
		if (StringUtils.isEmpty_DB(sID))
		{
			doRegister(request, output);
		}
		else
		{
			String sRequestType = request.getStringValue(REQUEST_TYPE);

			if (sRequestType.equals(UPDATE))
			{
				doUpdate(request, output);
			}
			else if (sRequestType.equals(DELETE))
			{
				deDelete(request, output);
			}

		}

	}

	private void doUpdate(JSONObjectWrapper request, JSONObject output)
	{
		JSONObjectWrapper entity = request.getJsonValue(USER);
		String sID = entity.getStringValue(getTable().ID.getName());

		Map<DatabaseColumn, String> mpValues = parseEntityValues(entity, getTable());

		IQueryResult result = getTable().update(sID, mpValues);

		if (result.getResult() == IQueryResult.SUCESS)
		{
			output.put(RESULT, true);
		}
		else
		{
			setFail(output, UNEXPECTED_ERROR, result.getError());
		}
	}

	private void deDelete(JSONObjectWrapper request, JSONObject output)
	{
		JSONObjectWrapper entity = request.getJsonValue(USER);

		String sID = entity.getStringValue(UsersTable.ID.getName());

		IQueryResult result = getTable().deleteID(sID);

		if (result.getResult() == IQueryResult.SUCESS)
		{
			output.put(RESULT, true);
		}
		else
		{
			setFail(output, UNEXPECTED_ERROR, result.getError());
		}
	}

	private void doRegister(JSONObjectWrapper request, JSONObject output)
	{
		JSONObjectWrapper entity = request.getJsonValue(USER);

		Map<DatabaseColumn, String> mpValues = parseEntityValues(entity, getTable());
		mpValues.put(UsersTable.ROLE, NOT_AUTHORIZED);

		IQueryResult result = getTable().insert(mpValues);

		if (result.getResult() == IQueryResult.SUCESS)
		{
			output.put(RESULT, true);
		}
		else
		{
			setFail(output, UNEXPECTED_ERROR, result.getError());
		}
	}

	@Override
	protected UsersTable getTable()
	{
		return (UsersTable) DatabaseService.getInstance().getTable(UsersTable.TABLE_NAME);
	}

}
